import logging
from typing import Any

from aiogram import Bot, types
from aiogram_dialog import DialogManager
from arq import ArqRedis
from fluentogram import TranslatorRunner
from pydantic import ValidationError
from sqlalchemy.exc import DBAPIError

from src.application.order.enums import OrderPeriod, OrderType
from src.config import Settings
from src.infrastructure.date_helpers import get_date_time
from src.infrastructure.db.services.stats import update_stats
from src.infrastructure.db.services.vpn_servers import get_free_vpn_server
from src.infrastructure.utils.helpers import get_expiring_on
from src.presentation.tg_bot.schemas.order import OrderModel
from src.presentation.tg_bot.services.tg_helpers import broadcast
from src.presentation.tg_bot.states import BuyVPNSG, VPNRouterSG

logger = logging.getLogger(__name__)


async def add_order(call: types.CallbackQuery, widget: Any, manager: DialogManager):
    arqredis: ArqRedis = manager.middleware_data.get("arqredis")
    locale: TranslatorRunner = manager.middleware_data.get("locale")
    bot: Bot = manager.middleware_data.get("bot")
    config: Settings = manager.middleware_data.get("config")

    vpn_summ: float = manager.dialog_data.get("vpn_summ")

    user_id: int = call.from_user.id

    user = await get_user(db_session, user_id)

    if widget.widget_id == "vpn_order":
        free_servers = await get_free_vpn_server(db_session, user)
        if len(free_servers) == 0:
            await call.answer(locale.get("no-free-vpn-servers"))
            return

    if user.balance < vpn_summ:
        await call.answer(locale.get("not-enough-balance", balance=user.balance))
        return

    try:
        if widget.widget_id == "vpn_order":
            period = OrderPeriod.one_month
            date_now = get_date_time()
            expiring_on = await get_expiring_on(date_now, period)
            category = await get_category_by_name(db_session, "VPN")
            type = OrderType.vpn
        else:
            period = OrderPeriod.unlimited
            expiring_on = None
            category = await get_category_by_name(db_session, "VPN Router")
            type = OrderType.vpn_router

        order = OrderModel(
            type=type,
            user_id=user_id,
            proxies=[],
            summ=vpn_summ,
            period=period,
            category_id=category.id,
            expiring_on=expiring_on,
        )

        order = await create_order(db_session, **order.dict())

        if widget.widget_id == "vpn_order":
            order.vpn_server = free_servers[0]
            await arqredis.enqueue_job(
                "generate_vpn_config_job",
                locale=locale,
                user_id=user_id,
                order_id=order.id,
            )
            logger.info(f"Добавлена задача на настройку впна для юзера {user_id}")
            await call.message.answer(locale.get("vpn-setup"))

        await call.message.answer(locale.get("order-success"))
        await update_stats(db_session, vpns=1)
        await db_session.commit()
        logger.info(f"Добавлен новый заказ на впн {order.id}")

        if widget.widget_id == "vpn_order":
            await manager.switch_to(BuyVPNSG.order_created)
        else:
            await manager.switch_to(VPNRouterSG.order_created)

    except (DBAPIError, ValidationError, Exception) as e:
        logger.exception(e)
        await call.answer(locale.get("error-msg"))
        await broadcast(
            bot,
            [config.tg_bot.developer_id],
            f"Ошибка во время создания заказа {str(e)}",
        )
